home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 2 / CU Amiga Magazine's Super CD-ROM 02 (1996)(EMAP Images)(GB)[!][issue 1996-04].iso / magazine / amiga_e / e_v3.2a_extras / pdsrc / findf.e < prev    next >
Text File  |  1994-07-01  |  5KB  |  245 lines

  1. /*
  2.  
  3.     findf
  4.  
  5.     A very fast case-sensitive grep-style search program using
  6.     async i/o and the Boyer-Moore search algorithm.
  7.  
  8.     Usage - same as 'c:search' for the commands implemented.
  9.  
  10.     Michael Zucchi 1994
  11.  
  12.  */
  13.  
  14.  
  15. MODULE 'dos/dos', 'dos/dosasl',
  16.     'locale',
  17.     'tools/async'
  18.  
  19. DEF skip[256]:ARRAY OF CHAR,    -> skip array
  20.     line[1024]:ARRAY OF CHAR,    -> input buffer
  21.     buffer[1024]:ARRAY OF CHAR,    -> for case-sensitive searches
  22.     m,                -> length of string
  23.     string:PTR TO CHAR,        -> string to match
  24.     uppertable[256]:ARRAY OF CHAR,-> lower->upper conversion table
  25.     quiet, nonum, quick, ncase    -> settings
  26.  
  27.  
  28. PROC main()
  29. DEF args:PTR TO LONG, rdargs, p:PTR TO LONG, an:PTR TO anchorpath,go,
  30.     fib:PTR TO fileinfoblock, loc, i
  31.  
  32. args:=[0,0,0,0,0,0,0];
  33.  
  34. IF rdargs:=ReadArgs('FROM/M,SEARCH/A,ALL/S,NONUM/S,QUIET/S,QUICK/S,CASE/S', args, 0)
  35.   string:=args[1];
  36.   nonum:=args[3];
  37.   quiet:=args[4];
  38.   quick:=args[5];
  39.   ncase:=args[6]=0;
  40.  
  41.   IF ncase
  42.     IF localebase:=OpenLibrary('locale.library', 0)
  43.       IF loc:=OpenLocale(0);
  44.         FOR i:=0 TO 255 DO uppertable[i]:=ConvToUpper(loc, i);
  45.         CloseLocale(loc);
  46.       ELSE
  47.         FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i
  48.       ENDIF
  49.     ELSE
  50.       FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i
  51.     ENDIF
  52.     CloseLibrary(localebase);
  53.     MOVE.L    uppertable,A0
  54.     MOVE.L    string,A1
  55.     MOVEQ    #0,D0
  56. mn_up:    MOVE.B    (A1),D0
  57.     MOVE.B    0(A0,D0.W),(A1)+
  58.     BNE.S    mn_up
  59.   ENDIF
  60.  
  61.   initskip();
  62.  
  63.   IF an:=New(SIZEOF anchorpath + 256)
  64.     an.strlen:=255
  65.     an.breakbits:=SIGBREAKF_CTRL_C;
  66.     fib:=an.info
  67.     p:=args[0];
  68.     go:=0
  69.     WHILE p[] AND (go=0)
  70.       go:=MatchFirst(p[], an);
  71.       WHILE go=0
  72.         IF (fib.direntrytype) <0
  73.       go:=scanfile(an+SIZEOF anchorpath);
  74.     ELSE
  75.           IF args[2]
  76.             IF (an.flags AND APF_DIRCHANGED)=0 THEN an.flags:=an.flags OR APF_DODIR
  77.           ENDIF
  78.         ENDIF
  79.         IF go=0 THEN go:=MatchNext(an);
  80.       ENDWHILE
  81.       p++
  82.     ENDWHILE
  83.     IF quick THEN WriteF('\e[M');
  84.     Dispose(an);
  85.   ENDIF
  86.   FreeArgs(rdargs);
  87. ELSE
  88.   WriteF('FindF, Michael Zucchi 1994.\nERROR: bad args\n'+
  89.       ' FROM/M    files/patterns to search\n'+
  90.       ' SEARCH/A  text to search for\n'+
  91.       ' ALL/S     recursively scan subdirectories\n'+
  92.       ' NONUM/S   do not output line numbers\n'+
  93.       ' QUIET/S   do not output matched lines\n'+
  94.       ' QUICK/S   faster file-scan display\n'+
  95.       ' CASE/S    do a case-sensitive search\n');
  96. ENDIF
  97. ENDPROC
  98.  
  99.  
  100. /*
  101.   search a single file, by filename, line at a time
  102.  */
  103.  
  104. PROC scanfile(name)
  105. DEF number, file, found=0,go=0
  106.  
  107. IF quick
  108.   WriteF('\s\e[K\b', name);
  109. ELSE
  110.   IF quiet=0 THEN WriteF('\s\n', name);
  111. ENDIF
  112.  
  113. number:=1;
  114. IF (file:=as_Open(name, MODE_OLDFILE, 3, 10240))
  115.   WHILE as_FGetS(file, line, 1023) AND (go=0)
  116.     IF testmatch()
  117.       IF quiet
  118.         IF found=0 THEN WriteF('\s\n', name);
  119.         JUMP close
  120.       ELSEIF nonum
  121. ->        IF quick AND found=0 THEN WriteF('\n');
  122.         WriteF('\s', line);
  123.       ELSE
  124. ->        IF quick AND found=0 THEN WriteF('\n');
  125.         WriteF('\d[6] \s', number, line);
  126.       ENDIF
  127.       found:=1
  128.     ENDIF
  129.     number++
  130.     go:=CheckSignal(SIGBREAKF_CTRL_C)
  131.   ENDWHILE
  132. close:
  133.   as_Close(file);
  134. ENDIF
  135.  
  136. ENDPROC go
  137.  
  138.  
  139.  
  140. /*
  141.   Initialise the skip table for a given search string
  142.  */
  143.  
  144. PROC initskip()
  145. DEF i
  146.  
  147. m:=StrLen(string);
  148.  
  149. -> initialise skip table for all characters
  150. FOR i:=0 TO 255
  151.   skip[i]:=m+1;
  152. ENDFOR
  153.  
  154. -> set skip table for characters in the string
  155. FOR i:=0 TO m-1
  156.   skip[string[i]]:=m-i;
  157. ENDFOR
  158.  
  159. ENDPROC
  160.  
  161. /*
  162.   Looks for a match in a given line
  163.  */
  164.  
  165. PROC testmatch()
  166.  
  167. IF m<1 THEN RETURN
  168.  
  169.     MOVEM.L    A4-A5,-(A7)
  170.  
  171.     MOVE.L    m,D7
  172.     SUBQ.L    #1,D7
  173.  
  174.     TST.L    ncase
  175.     BEQ.S    tm_case
  176.  
  177.     -> non case-sensitive
  178.  
  179.     MOVE.L    line,A3
  180.     MOVE.L    buffer,A0
  181.     LEA    1(A0,D7.L),A2
  182.     MOVE.L    uppertable,A1
  183.     MOVEQ    #0,D0
  184. tp_up:    MOVE.B    (A3)+,D0
  185.     MOVE.B    0(A1,D0.W),(A0)+
  186.     BNE.S    tp_up
  187.     BRA.S    tp_match
  188.  
  189.     -> case sensitive
  190. tm_case:
  191.     MOVE.L    line,A0
  192.     LEA    1(A0,D7.L),A2    -> a[i]
  193. tm_scan:
  194.     TST.B    (A0)+        -> <hack> find end of string
  195.     BNE.S    tm_scan
  196.  
  197. tp_match:
  198.     MOVE.L    string,A1
  199.     MOVE.L    A1,A5
  200.     LEA    1(A1,D7.L),A1    -> p[j]
  201.  
  202.     MOVE.L    skip,A4
  203.  
  204.     MOVE.L    D7,D3
  205.     ADDQ.L    #2,D3
  206.     MOVEQ    #0,D1
  207. tm_loop0:
  208.     MOVE.L    D7,D2
  209.     MOVE.L    A1,A3
  210. tm_loop:
  211.     MOVE.B    -(A2),D1
  212.     CMP.B    -(A3),D1
  213.     BEQ.S    tm_matchchar
  214.  
  215.     MOVE.L    A5,D0
  216.     SUB.L    A3,D0        -> -j
  217.     ADD.L    D3,D0        -> M-j+1
  218.  
  219.     MOVE.B    0(A4,D1.W),D1    -> skip[character]
  220.     CMP.L    D0,D1
  221.     BLT.S    tm_add0
  222.  
  223.     ADD.L    D1,A2
  224.  
  225. tm_ok:    CMPA.L    A0,A2
  226.     BLT.S    tm_loop0
  227.  
  228.     MOVEQ    #0,D0
  229.     BRA.S    tm_exit
  230.  
  231. tm_add0:
  232.     ADD.L    D0,A2
  233.     BRA.S    tm_ok
  234.  
  235. tm_matchchar:
  236.     DBF    D2,tm_loop
  237.  
  238.     MOVEQ    #-1,D0
  239. tm_exit:
  240.     MOVEM.L    (A7)+,A4-A5
  241.  
  242. ENDPROC    D0
  243.  
  244.  
  245.